/*
 *  e100_write.c
 *  
 *
 *  Created by Yingkai Hu on 12/3/11.
 *  Copyright 2011 NYU. All rights reserved.
 *
 */

#include <xinu.h>

/*------------------------------------------------------------------------
 * e100_write - write a packet to an E100 device
 *------------------------------------------------------------------------
 */
devcall	e100_write(
	struct	ether *ethptr, 		/* ptr to entry in ethertab 	*/
	void	*buf,			/* buffer that holds a packet	*/
	uint32	len			/* length of buffer		*/
	)
{
	struct 	e100_tx_desc *descptr;/* ptr to ring descriptor 	*/
	char 	*pktptr; 		/* ptr used during packet copy  */
	uint32	tail;			/* index of ring buffer for pkt	*/
	struct 	e100_tx_desc *prev;
	//uint32 	tdt;
	
	/* Wait for a free ring slot */
	//kprintf("Tx sem num = %d\r\n", ethptr->osem);
	wait(ethptr->osem);
	//kprintf("========================write starts========================\r\n");
	//kprintf("ethptr->osem = %d\r\n", ethptr->osem);
	
	/* Find the tail of the ring to insert packet */
	
	tail = ethptr->txTail;
	descptr = (struct e100_tx_desc *)ethptr->txRing + tail;

	prev	= (struct e100_tx_desc *)ethptr->txRing + (tail-1)%ethptr->txRingSize;

	/* Copy packet to transmit ring buffer */
	
	pktptr = (char *)((uint32)descptr->u.tcb.data);
	//pktptr = (char *)getmem(len);
	memcpy(pktptr, buf, len);
	/* kprintf("pktptr 10 character is %d\r\n", (int)pktptr[10]);
	kprintf("pktptr 11 character is %d\r\n", (int)pktptr[11]);
	kprintf("pktptr 12 character is %d\r\n", (int)pktptr[12]);
	kprintf("pktptr 13 character is %d\r\n", (int)pktptr[13]);
	kprintf("pktptr 14 character is %d\r\n", (int)pktptr[14]);	*/
	
	if (descptr->status & cb_complete) {
		kprintf("descptr->status == cb_complete\r\n");
	}
	if (descptr->status & cb_ok) {
		kprintf("descptr->status == cb_ok\r\n");
	}
	if (prev->status & cb_complete) {
		kprintf("prev->status == cb_complete\r\n");
	}
	if (prev->status & cb_ok) {
		kprintf("prev->status == cb_ok\r\n");
	}
	
	descptr->command = cb_tx | cb_i;
	descptr->status &= 0x0000;
	descptr->u.tcb.tcb_byte_count=len;
	descptr->u.tcb.tcb_byte_count |= 0x8000;
	//descptr->u.tcb.tcb_byte_count |= ((0x3FFF)&(uint16)len);
	descptr->u.tcb.tbd_array = 0xFFFFFFFF;
	descptr->u.tcb.threshold = 0xE0;
	descptr->u.tcb.tbd_num = 0;
	
	//kprintf("In e100_write, descptr = %d\r\n", (int32)descptr);
	/*kprintf("before !(descptr->status & cb_complete) = %d\r\n", !(descptr->status & cb_complete));	
	if (!(descptr->status & cb_complete)){
		kprintf("asdfghhhjhh\n");
		}
	kprintf("After !(descptr->status & cb_complete) = %d\r\n", !(descptr->status & cb_complete));
	*/
	kprintf("ethptr->txHead = %d\r\n", ethptr->txHead);
	kprintf("ethptr->txTail = %d\r\n", ethptr->txTail);

	//ethptr->txTail = (ethptr->txTail + 1) % ethptr->txRingSize;
	
	descptr->command |= (uint16)cb_s;
	if (ethptr->txHead != ethptr->txTail) {
		prev->command &= ~((uint16)cb_s);
		kprintf("prev->command = %4x\r\n", prev->command);
	} else {
		e100_exec_cmd(ethptr, cuc_resume, 0);
	}
	
	ethptr->txTail = (ethptr->txTail + 1) % ethptr->txRingSize;
	
	kprintf("========================write ends========================\r\n");
	return len;
}

